package bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Formatter;
import java.util.List;

import util.StatusJogo;


/**
 * Classe que armazena/manipula caracteristicas de um Jogo
 * @author Claudio Cardoso, Daniel Leite, Lucas Sampaio, Matheus Sampaio
 * @version 1.0
 */


public class Jogo implements Comparable<Jogo>, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String timeA, timeB;
	private int golsA, golsB;
	private Calendar horario;
	private StatusJogo statusDoJogo;
	private List<Palpite> palpites = new ArrayList<Palpite>();

	//construtor
	public Jogo(String timeA, String timeB, Calendar horario)
			throws IllegalArgumentException {

		setTimeA(timeA);
		setTimeB(timeB);
		setHorario(horario);
		setStatusDoJogo(StatusJogo.ABERTO);
		if (timeA.equals(timeB)) {
			throw new IllegalArgumentException("Os times devem ser diferentes");
		}

	}

	/**
	 * Retorna o Nome do TimeA ("Mandante") do Jogo
	 * @return Time1
	 * 		Time "Mandante" do Jogo
	 */
	public String getTimeA() {
		return timeA;
	}

	/**
	 * Modifica o Nome do TimeA ("Mandante") do Jogo
	 * @param timeA
	 *            Novo Nome do TimeA
	 */
	public void setTimeA(String timeA) throws IllegalArgumentException {
		if (timeA == null || timeA.trim().equals("")) {
			throw new IllegalArgumentException();
		}
		this.timeA = timeA;
	}

	/**
	 * Retorna o Nome do TimeB ("Visitante") do Jogo
	 * @return TimeB
	 * 		Time "Visitante" do Jogo
	 */
	public String getTimeB() {
		return timeB;
	}

	/**
	 * Modifica o Nome do TimeB ("Visitante") do Jogo
	 * @param timeB
	 *            Novo Nome do TimeB
	 */
	public void setTimeB(String timeB) throws IllegalArgumentException {
		if (timeB == null || timeB.trim().equals("")) {
			throw new IllegalArgumentException();
		}
		this.timeB = timeB;
	}

	/**
	 * Retorna Horario do Jogo
	 * @return 
	 * 		Horario do Jogo
	 */
	public Calendar getHorario() {
		return horario;
	}

	/**
	 * Modifica Horario do Jogo
	 * @param horario
	 *            Novo Horario do Jogo
	 */
	public void setHorario(Calendar horario) {
		this.horario = horario;
	}

	/**
	 * Retorna a quantidade de Gols do TimeA
	 * @return 
	 * 		Gols do TimeA
	 */
	public int getGolsA() {
		return golsA;
	}

	/**
	 * Modifica a quantidade de gols do TimeA
	 * @param golsA
	 *		Novo Placar do TimeA
	 */
	public boolean setGolsA(int golsA) throws IllegalArgumentException {
		if (golsA < 0) {   //Gols nao podem ser negativo
			throw new IllegalArgumentException();
		}
		this.golsA = golsA;
		return true;
	}

	/**
	 * Retorna a quantidade de Gols do TimeB
	 * @return 
	 * 		Gols do TimeB
	 */
	public int getGolsB() {
		return golsB;
	}

	/**
	 * Modifica a quantidade de gols do TimeB
	 * @param golsB
	 *       Novo Placar do  Gols do TimeB
	 */
	public boolean setGolsB(int golsB) throws IllegalArgumentException {
		if (golsB < 0) {  //Gols nao podem ser negativos
			throw new IllegalArgumentException();
		}
		this.golsB = golsB;
		return true;
	}

	/**
	 * Modifica o status do Jogo
	 * @param statusDoJogo
	 *            Novo status do Jogo
	 */
	public void setStatusDoJogo(StatusJogo statusDoJogo) {
		this.statusDoJogo = statusDoJogo;
	}

	/**
	 * Retorna o status do Jogo
	 * @return 
	 * 		Status do Jogo
	 */
	public StatusJogo getStatusDoJogo() {
		return statusDoJogo;
	}

	/**
	 * Retorna os Palpites dos Jogadores
	 * @return 
	 * 		Palpites dos Jogadores
	 */
	public List<Palpite> getPalpites() {
		return palpites;
	}

	/**
	 * Adiciona palpite do Jogador
	 * @param palpite
	 *            Palpite a ser adicionado
	 */
	public void addPalpite(Palpite palpite) {
		palpites.add(palpite);
	}
	
	/**
	 * Pesquisa se ja foi dado palpite em determinado Jogo
	 * @param jogador
	 *      Jogador que palpitou
	 * @return 
	 * 		Palpite, se houver um palpite do jogador. Caso contrario, null.
	*/
	public Palpite pesquisaPalpite(Jogador jogador) {
		for (Palpite palpite : getPalpites()) {
			if (palpite.getJogador().equals(jogador)) {
				return palpite;
			}
		}
		return null;
	}
	
	/**
	 * Saida na tela do Jogo com o palpite do Jogador
	 * @param jogador
	 * 		Jogador Logado
	 * @return
	 * 		Retorna uma String com os gols que o jogador palpitou e a pontuacao que o jogador obteve no jogo
	 */
	public String jogoComPalpite(int pontuacao, Jogador jogador) {
		Formatter formatter = new Formatter();
		Palpite palpite = pesquisaPalpite(jogador);
		formatter.format("%1$td/%1$tm/%1$tY %1$tRh - %2$20s %3$4d x %4$-4d %5$-20s  Pontos: %5$3d", getHorario(), getTimeA(), palpite.getGolsTimeA(), palpite.getGolsTimeB(), getTimeB(), pontuacao);
		return formatter.toString();
	}
	
	/**
	 * Saida na tela do Jogo sem palpite
	 * @return
	 * 		Retorna a string sem valor nos gols
	 */
	public String jogoSemPalpite() {
		Formatter formatter = new Formatter();
		formatter.format("%1$td/%1$tm/%1$tY %1$tRh - %2$20s %3$4s x %4$-4s %5$-20s", getHorario(), getTimeA(), "", "", getTimeB());
		return formatter.toString();
	}
	
	/**
	 * Saida na tela do Jogo sem palpite
	 * @return
	 * 		Nao havendo palpite do jogador neste jogo, retorna uma String no formato TimeA x TimeB
	 */
	public String semResultado(int indice) {
		Formatter formatter = new Formatter();
		
		formatter.format("%1$3d - %2$20s %3$4s x %4$-4s %5$-20s  (Sem Resultado)", indice, getTimeA(), "", "", getTimeB());
		
		return formatter.toString();
	}
	
	/**
	 * Saida na tela do Jogo com resultado
	 * @param indice
	 * 		Indice do jogo
	 * @param pontuacao
	 * 		Pontuacao que o Jogador obteve nesse jogo
	 * @return
	 * 		String do jogo com o resultado e a pontuacao do jogador neste palpite
	 */
	public String comResultado(int indice, int pontuacao) {
		Formatter formatter = new Formatter();
		
		formatter.format("%1$3d - %2$20s %3$4d x %4$-4d %5$-20s  Pontos: %6$3d", indice, getTimeA(), getGolsA(), getGolsB(), getTimeB(), pontuacao);
		
		return formatter.toString();
	}
	
	/**
	 * Retorna resultado do Jogo
	 * @return 
	 * 		Informacoes sobre o jogo
	 */
	public String toString() {
		Formatter formatter = new Formatter();
		formatter.format("%20s %2d x %-2d %-20s", getTimeA(), getGolsA(), getGolsB(), getTimeB());
		return formatter.toString();
	}

	@Override
	/**
	 * Compara dois jogos
	 */
	public int compareTo(Jogo jogo) {
		return this.horario.compareTo(jogo.getHorario());
	}

	@Override
	/**
	 * Verifica a Igualdade entre dois Jogos
	 * @return
	 * 		True, se os jogos forem iguais. False, caso contrario
	 */
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Jogo))
			return false;
		Jogo other = (Jogo) obj;
		if (golsA != other.getGolsA())
			return false;
		if (golsB != other.getGolsB())
			return false;
		if (horario == null) {
			if (other.getHorario() != null)
				return false;
		} else if (!horario.equals(other.horario))
			return false;
		if (timeA == null) {
			if (other.timeA != null)
				return false;
		} else if (!timeA.equals(other.timeA))
			return false;
		if (timeB == null) {
			if (other.timeB != null)
				return false;
		} else if (!timeB.equals(other.timeB))
			return false;
		return true;
	}

}

